From a26b775b7bbf1abd3e99c8bf9ce4c7522d3a0adc Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Wed, 19 Jan 2022 13:56:34 +0100
Subject: chore: add structured data using schema.org and JSON-LD

I also added the featured image on single article.
---
 src/pages/article/[slug].tsx | 67 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 2 deletions(-)

(limited to 'src/pages/article/[slug].tsx')

diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx
index e519c27..8c345b7 100644
--- a/src/pages/article/[slug].tsx
+++ b/src/pages/article/[slug].tsx
@@ -18,6 +18,7 @@ import { useEffect } from 'react';
 import styles from '@styles/pages/Page.module.scss';
 import { Sharing, ToC } from '@components/Widgets';
 import Sidebar from '@components/Sidebar/Sidebar';
+import { Blog, BlogPosting, Graph, WebPage } from 'schema-dts';
 
 const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
   const {
@@ -26,6 +27,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
     content,
     databaseId,
     dates,
+    featuredImage,
     intro,
     seo,
     subjects,
@@ -52,13 +54,74 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
     translateCopyButton(locale);
   }, [locale]);
 
+  const webpageSchema: WebPage = {
+    '@id': `${config.url}${router.asPath}`,
+    '@type': 'WebPage',
+    breadcrumb: { '@id': `${config.url}/#breadcrumb` },
+    lastReviewed: dates.update,
+    name: seo.title,
+    description: seo.metaDesc,
+    reviewedBy: { '@id': `${config.url}/#branding` },
+    url: `${config.url}${router.asPath}`,
+    isPartOf: {
+      '@id': `${config.url}`,
+    },
+  };
+
+  const blogSchema: Blog = {
+    '@id': `${config.url}/#blog`,
+    '@type': 'Blog',
+    blogPost: { '@id': `${config.url}/#article` },
+    isPartOf: {
+      '@id': `${config.url}${router.asPath}`,
+    },
+    license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
+  };
+
+  const publicationDate = new Date(dates.publication);
+  const updateDate = new Date(dates.update);
+
+  const blogPostSchema: BlogPosting = {
+    '@id': `${config.url}/#article`,
+    '@type': 'BlogPosting',
+    name: title,
+    description: intro,
+    articleBody: content,
+    author: { '@id': `${config.url}/#branding` },
+    commentCount: comments.length,
+    copyrightYear: publicationDate.getFullYear(),
+    creator: { '@id': `${config.url}/#branding` },
+    dateCreated: publicationDate.toISOString(),
+    dateModified: updateDate.toISOString(),
+    datePublished: publicationDate.toISOString(),
+    discussionUrl: `${config.url}${router.asPath}/#comments`,
+    editor: { '@id': `${config.url}/#branding` },
+    image: featuredImage?.sourceUrl,
+    inLanguage: config.defaultLocale,
+    isPartOf: {
+      '@id': `${config.url}/blog`,
+    },
+    license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
+    mainEntityOfPage: { '@id': `${config.url}${router.asPath}` },
+    thumbnailUrl: featuredImage?.sourceUrl,
+  };
+
+  const schemaJsonLd: Graph = {
+    '@context': 'https://schema.org',
+    '@graph': [webpageSchema, blogSchema, blogPostSchema],
+  };
+
   return (
     <>
       <Head>
         <title>{seo.title}</title>
         <meta name="description" content={seo.metaDesc} />
+        <script
+          type="application/ld+json"
+          dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
+        ></script>
       </Head>
-      <article className={styles.article}>
+      <article id="article" className={styles.article}>
         <PostHeader intro={intro} meta={meta} title={title} />
         <Sidebar position="left">
           <ToC />
@@ -73,7 +136,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
         </Sidebar>
         <section id="comments" className={styles.comments}>
           <CommentsList articleId={databaseId} comments={comments} />
-          <CommentForm articleId={post.databaseId} />
+          <CommentForm articleId={databaseId} />
         </section>
       </article>
     </>
-- 
cgit v1.2.3

